/*
*
* KMLReader
*
* This class reads neighbourhood coordinates, names, descriptions, and numbers from the KML
* file supplied on data.edmonton.ca.
*
*/

class KMLReader {
  
 // attributes
 String[] names;
 String[] pollids;
 String[] shortNames;
 String[] psbWards;
 String[] csbWards;
 String[] coordStrings; 
 String[][] out;
 PApplet parent;
 
 // constructor method
 KMLReader(PApplet p) {
   parent = p;
 }
 
 // read method -- returns data read from KML file in project data directory
 String[][] readKML() {
   
  // drill down in neighbourhood elements, which are children of "document" element
  XMLElement kml;
  kml = new XMLElement(parent, "votingSubdivisions.xml");
  XMLElement document = kml.getChild(0);
  int n = document.getChildCount();
  
  // create arrays for data storage
  names = new String[n-1];
  pollids = new String[n-1];
  shortNames = new String[n-1];
  psbWards = new String[n-1];
  csbWards = new String[n-1];
  coordStrings = new String[n-1];
  out = new String[6][n-1];
  
  // iterate through neighbourhoods and extract name, description, neighbourhood
  // number, and coordinates
  for (int i = 1; i < n; i++) {
    
    // read data and store in arrays
    XMLElement placemark = document.getChild(i);
    XMLElement name = placemark.getChild(0);
    names[i-1] = name.getContent();
    
    XMLElement extendedData = placemark.getChild(4);
    XMLElement schemaData = extendedData.getChild(0);
    
    XMLElement pollid = schemaData.getChild(0);
    pollids[i-1] = pollid.getContent();
    
    XMLElement shortName = schemaData.getChild(1);
    shortNames[i-1] = shortName.getContent();
    
    XMLElement psbWard = schemaData.getChild(5);
    psbWards[i-1] = psbWard.getContent();
    
    XMLElement csbWard = schemaData.getChild(6);
    csbWards[i-1] = csbWard.getContent();
    
    // check for MultiGeometry element; if it exists, neighbourhood 
    // is composed of multiple non-contiguous polygons
    if (placemark.getChild(5).getName().equals("Polygon")) {
      XMLElement polygon = placemark.getChild(5);
      XMLElement outerBound = polygon.getChild(0);
      XMLElement linearRing = outerBound.getChild(0);
      XMLElement coords = linearRing.getChild(0);
      coordStrings[i-1] = coords.getContent();
    } else {
      XMLElement multiGeom = placemark.getChild(5);
      
      String[] polys = new String[multiGeom.getChildCount()];
      
      for(int j = 0; j < (multiGeom.getChildCount()); j++) {
        XMLElement polygon = multiGeom.getChild(j);
        XMLElement outerBound = polygon.getChild(0);
        XMLElement linearRing = outerBound.getChild(0);
        XMLElement coords = linearRing.getChild(0);
        polys[j] = coords.getContent();    
      } // for loop
      
      coordStrings[i-1] = join(polys, ":");
      
    } // if
  } // for loop

  // return array
  out[0] = names;
  out[1] = pollids;
  out[2] = shortNames;
  out[3] = psbWards;
  out[4] = csbWards;
  out[5] = coordStrings;

  return out;
   
 } // readKML method
 
 // readNInfo method; reads neighbourhood data; currently designed to read from
 // a .csv created by Mack Male as "official" data not available from city yet
 String[][] readNInfo() {
   
   // read data from csv
   String[] lines = loadStrings("Census2009.csv");
   
   // initialize arrays
   String[][] out = new String[lines.length - 1][split(lines[0], ",").length];
   String[] lin;
   
   // iterate through lines -- start at index 1, as first line is column headers
   for(int i = 1; i < lines.length; i++) {
     
     // split lines on comma
     lin = split(lines[i], ",");
     
     // iterate through line elements
     for(int j = 0; j < lin.length; j++) {
       
       // store value in output array
       out[i - 1][j] = lin[j];
       
     } // for j
     
     // trim name and convert to uppercase
     out[i - 1][0] = trim(out[i - 1][0]).toUpperCase();
     
   } // for i
   
   return out;
   
 } // readNInfo
 
  // readElectionInfo method; reads 2010 Edmonton Election results
  String[][] readElectionInfo() {
   
   // read data from csv
   String[] lines = loadStrings("2010_Election_Final_Results.csv");
   
   // initialize arrays
   String[][] out = new String[lines.length][split(lines[0], ",").length];
   String[] lin;
   
   // iterate through lines
   for(int i = 0; i < lines.length; i++) {
     
     // split lines on comma
     lin = split(lines[i], ",");
     
     // iterate through line elements
     for(int j = 0; j < lin.length; j++) {
       
       // store value in output array
       out[i][j] = lin[j];
       
     } // for j
     
     // trim StationName and Candidate name and convert to upper case;
     out[i][6] = trim(out[i][6]).toUpperCase();
     out[i][10] = trim(out[i][10]).toUpperCase();
     
   } // for i
   
   return out;
   
 } // readElectionInfo
   
  // readNOtherInfo method; reads neighbourhood data not included in the census;
  // currently designed to read a csv created by hand by my loving girlfriend
 String[][] readNOtherInfo() {
   
   // read data from csv
   String[] lines = loadStrings("neighbourhood-other.csv");
   
   // initialize arrays
   String[][] out = new String[lines.length][split(lines[0], ",").length];
   String[] lin;
   
   // iterate through lines
   for(int i = 0; i < lines.length; i++) {
     
     // split lines on comma
     lin = split(lines[i], ",");
     
     // iterate through line elements
     for(int j = 0; j < lin.length; j++) {
       
       // store value in output array
       out[i][j] = lin[j];
       
     } // for j
     
     // trim name and convert to uppercase
     out[i][0] = trim(out[i][0]).toUpperCase();
     
   } // for i
   
   return out;
   
 } // readNOtherInfo   
 
} // class
